/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package hcmus.fit.master.sevensea.background;

import hcmus.fit.master.sevensea.control.Control;
import hcmus.fit.master.sevensea.core.AbstractLayer;
import hcmus.fit.master.sevensea.core.AbstractSprite;
import hcmus.fit.master.sevensea.core.Constant;
import hcmus.fit.master.sevensea.core.Sprite;
import hcmus.fit.master.sevensea.sprite.Island;
import hcmus.fit.master.sevensea.sprite.Rubble;
import hcmus.fit.master.sevensea.sprite.Splash;
import hcmus.fit.master.sevensea.sprite.Whirl;
import hcmus.fit.master.sevensea.sprite.ship.BlackPirate;
import hcmus.fit.master.sevensea.sprite.ship.BluePirate;
import hcmus.fit.master.sevensea.sprite.ship.Cannon;
import hcmus.fit.master.sevensea.sprite.ship.Explosion;
import hcmus.fit.master.sevensea.sprite.ship.GhostShip;
import hcmus.fit.master.sevensea.sprite.ship.GoodShip;
import hcmus.fit.master.sevensea.sprite.ship.RedPirate;
import hcmus.fit.master.sevensea.sprite.ship.Ship;
import hcmus.fit.master.sevensea.sprite.ship.ShipState;
import hcmus.fit.master.sevensea.util.Size;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;

/**
 * 
 * @author hvp
 */
public class Sea implements Sprite {
    private Size viewSize;
    public int busy;
    public List<Sprite> items;
    public GoodShip mainShip;
    public AbstractSprite[][] map;
    public static List<int[]> levelInfomation;
    private int level;
    public Control boardControl;
    public boolean gameOver;
    // public static Player Sound ;
    public List<Sprite> backUp;
    public boolean canUndo;
    public boolean levelComplete;
    public static Bitmap resource;
    public List<AbstractLayer> layers;
    public Point globalPos;

    public Sea(Size size, int lv) {
        level = lv + 1;
        viewSize = size;
        // Index = 0;
        // Frames = (Image[]) Resource.get(0);
        // NumberOfFrame = Frames.length;
        items = new ArrayList<Sprite>();
        layers = new ArrayList<AbstractLayer>();
        layers.add(new WaveLayer(viewSize));
        layers.add(new BorderLayer(viewSize));
        generate();
        backUp = new ArrayList<Sprite>();
        canUndo = false;
        globalPos = new Point(0, 0);
    }

    public void generate() {
        if (level <= levelInfomation.size()) {
            busy = 0;
            items = new ArrayList<Sprite>();
            items.clear();
            levelComplete = false;
            gameOver = false;

            map = new AbstractSprite[Constant.Height][];
            for (int i = 0; i < Constant.Height; i++) {
                map[i] = new AbstractSprite[Constant.Width];
            }

            generateGoodShip();
            generateIsland(3);
            generateWhirl(4);
            int[] tmp = (int[]) levelInfomation.get(level - 1);

            generateBlackPirate(tmp[0]);
            generateRedPirate(tmp[1]);
            generateBluePirate(tmp[2]);
            generateGhostShip(tmp[3]);
            items.remove(mainShip);
            items.add(mainShip);
        }
    }

    public static List<List<Bitmap>> getResource(Bitmap resource, int num, int den) {
        List<List<Bitmap>> rs = new ArrayList<List<Bitmap>>();
        rs.clear();
        int w = resource.getWidth();
        int h = resource.getHeight();

        List<Bitmap> tmp = new ArrayList<Bitmap>();
        tmp.add(Bitmap.createBitmap(w, h, Constant.BITMAP_CONFIG));
        Canvas g = new Canvas(tmp.get(0));
        g.drawBitmap(resource, 0, 0, new Paint());

        rs.add(tmp);
        return rs;
    }

    public static void UnLoadResource() {
        levelInfomation = null;

        GoodShip.Resource = null;
        GoodShip.NumOfStatus = 0;

        GoodShip.ShipWhirl = null;

        Cannon.Resource = null;

        Explosion.Resource = null;

        Island.Resource = null;

        Whirl.Resource = null;

        BlackPirate.Resource = null;
        BlackPirate.NumOfStatus = 0;

        Splash.Resource = null;

        Rubble.Resource = null;

        RedPirate.Resource = null;
        RedPirate.NumOfStatus = 0;

        BluePirate.Resource = null;
        BluePirate.NumOfStatus = 0;

        GhostShip.Resource = null;
        GhostShip.NumOfStatus = 0;
    }

    public void generateGoodShip() {
        mainShip = new GoodShip(this, Constant.Width / 2, Constant.Height / 2);
        map[Constant.Height / 2][Constant.Width / 2] = mainShip;
        items.add(mainShip);
    }

    public void generateBlackPirate(int num) {
        Random r = new Random();
        for (int i = 0; i < num; i++) {
            boolean run;
            int x, y;
            do {
                run = false;
                x = r.nextInt(Constant.Width);
                y = r.nextInt(Constant.Height);
                if (map[y][x] != null
                        || ((x >= mainShip.X - 2) && (x <= mainShip.X + 2) && (y >= mainShip.Y - 2) && (y <= mainShip.Y + 2))) {
                    run = true;
                }
            } while (run);
            BlackPirate ship = new BlackPirate(this, x, y);
            items.add(ship);
            map[y][x] = ship;
        }
    }

    public void generateRedPirate(int num) {
        Random r = new Random();
        for (int i = 0; i < num; i++) {
            boolean run;
            int x, y;
            do {
                run = false;
                x = r.nextInt(Constant.Width);
                y = r.nextInt(Constant.Height);
                if (map[y][x] != null
                        || ((x >= mainShip.X - 2) && (x <= mainShip.X + 2) && (y >= mainShip.Y - 2) && (y <= mainShip.Y + 2))) {
                    run = true;
                }
            } while (run);
            RedPirate ship = new RedPirate(this, x, y);
            items.add(ship);
            map[y][x] = ship;
        }
    }

    public void generateBluePirate(int num) {
        Random r = new Random();
        for (int i = 0; i < num; i++) {
            boolean run;

            int x, y;
            do {
                run = false;
                x = r.nextInt(Constant.Width);
                y = r.nextInt(Constant.Height);
                if (map[y][x] != null
                        || ((x >= mainShip.X - 2) && (x <= mainShip.X + 2) && (y >= mainShip.Y - 2) && (y <= mainShip.Y + 2))) {
                    run = true;
                }
            } while (run);
            BluePirate ship = new BluePirate(this, x, y);
            items.add(ship);
            map[y][x] = ship;
        }
    }

    public void generateGhostShip(int num) {
        Random r = new Random();
        for (int i = 0; i < num; i++) {
            boolean run;
            int x, y;
            do {
                run = false;
                x = r.nextInt(Constant.Width - 1);
                y = r.nextInt(Constant.Height - 1);
                if (map[y][x] != null) {
                    run = true;
                }
            } while (run);
            GhostShip ship = new GhostShip(this, x, y);
            items.add(ship);
            map[y][x] = ship;
        }
    }

    public void generateIsland(int num) {
        Random r = new Random();

        for (int i = 0; i < num; i++) {
            boolean run;
            int x, y;
            do {
                run = false;
                x = r.nextInt(Constant.Width);
                y = r.nextInt(Constant.Height);
                if (map[y][x] != null)
                    run = true;
            } while (run);
            Island il = new Island(this, x, y);
            items.add(il);
            map[y][x] = il;
        }
    }

    public void generateWhirl(int num) {
        Random r = new Random();

        for (int i = 0; i < num; i++) {
            boolean run;

            int x, y;
            do {
                run = false;
                x = r.nextInt(Constant.Width);
                y = r.nextInt(Constant.Height);
                if (map[y][x] != null)
                    run = true;
            } while (run);
            Whirl wh = new Whirl(this, x, y);
            items.add(wh);
            map[y][x] = wh;
        }
    }

    public void draw(Canvas canvas) {
        Bitmap tmp = Bitmap.createBitmap(Constant.MAP_WIDTH + Constant.PadLeft + Constant.PadRight,
                Constant.MAP_HEIGHT + Constant.PadTop + Constant.PadBottom, Constant.BITMAP_CONFIG);
        Canvas c = new Canvas(tmp);
        // Bitmap tmp = Bitmap.createBitmap(BackGround.getWidth(),
        // BackGround.getHeight(), Constant.BITMAP_CONFIG);
        // g.setColor(0, 0, 50);
        // g.fillRect(0, 0, BackGround.getWidth() + Configuration.PadLeft +
        // Configuration.PadRight - 1, BackGround.getHeight() +
        // Configuration.PadTop + Configuration.PadBottom - 1);

        // g.drawBitmap(BackGround, Constant.PadLeft, Constant.PadTop, new
        // Paint());
        for (AbstractLayer layer : layers) {
            layer.draw(c);
        }
        // g.drawBitmap(BackGround, Constant.PadLeft, Constant.PadTop, new
        // Paint());
        /*
         * g.DrawImage(Frames[Index], new Rectangle(Configuration.PadLeft,
         * Configuration.PadTop, Frames[Index].Width, Frames[Index].Height), 0,
         * 0, Frames[Index].Width, Frames[Index].Height, GraphicsUnit.Pixel,
         * imgatt);
         */

        for (int i = 0; i < items.size(); i++) {
            AbstractSprite item = (AbstractSprite) items.get(i);
            item.draw(c);
        }
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.RED);
        int l = this.mainShip.getRealPos().x;
        int t = this.mainShip.getRealPos().y;
        c.drawRect(new Rect(l - Constant.CELL_WIDTH, t - Constant.CELL_HEIGHT,
                l+Constant.CELL_WIDTH*2, t + Constant.CELL_HEIGHT*2), paint);

        // BoardControl._Life.Show(g, Configuration.TotalLeft +
        // MainShip.Position.X, Configuration.TotalTop + MainShip.Position.Y);

        int left = mainShip.getRealPos().x - (viewSize.Width - Constant.CELL_WIDTH) / 2
                + Constant.TotalLeft;
        int top = mainShip.getRealPos().y
                - (viewSize.Height - Constant.ControlHeight - Constant.CELL_HEIGHT) / 2
                + Constant.TotalTop;
        int right = viewSize.Width + left;
        int bottom = (viewSize.Height - Constant.ControlHeight) + top;
//        canvas.drawBitmap(tmp, new Rect(0, 0, viewSize.Width, viewSize.Height), new Rect(0, 0, viewSize.Width,
//                viewSize.Height), new Paint());
        canvas.drawBitmap(tmp, new Rect(left, top, right, bottom), new Rect(0, 0, viewSize.Width,
                viewSize.Height), new Paint());

        globalPos.set(0-left, 0-top);
        // g1.drawBitmap(tmp, 0, 0, new Paint());
        /*
         * g1.DrawImage(tmp, new Rectangle(0, 0, _size.Width, _size.Height -
         * Configuration.ControlHeight), MainShip.Position.X - (_size.Width -
         * Configuration.CellWidth) /2 + Configuration.TotalLeft,
         * MainShip.Position.Y - (_size.Height - Configuration.ControlHeight -
         * Configuration.CellHeight) /2 + Configuration.TotalTop, _size.Width,
         * (_size.Height - Configuration.ControlHeight), GraphicsUnit.Pixel,
         * imgatt);
         */
    }

    public Point translateToGlobalView(Point p) {
        return new Point(p.x + globalPos.x , p.y + globalPos.y);
    }
    public boolean win() {
        for (int i = 0; i < items.size() - 1; i++) {
            if (((AbstractSprite) items.get(i)).isShip() && !items.get(i).equals(mainShip)) {
                return false;
            }
        }
        return true;
    }

    public boolean close() {
        if (items.contains(mainShip))
            return false;
        return true;
    }

    public void enemyMove() {
        for (int i = 0; i < items.size(); i++) {
            if (((AbstractSprite) items.get(i)).isEnemy()) {
                busy++;
                Ship s = (Ship) items.get(i);
                s.GetDirection(mainShip.X, mainShip.Y);
                s.GetDestination();
                s.State = ShipState.Rotating;
                map[s.Y][s.X] = null;

            }
        }
        busy--;// busy cua mainship
    }

    public void nextLevel() {
        busy++;
        levelComplete = true;
    }

    public void changeLevel() {
        level++;
        boardControl._Level.LEVEL++;
        generate();
    }

    public void reloadCurrentLevel() {
        generate();
    }

    public void createExplosion(int x, int y) {
        Explosion e = new Explosion(this, x, y);
        // Explosion.Sound.Play();
        items.add(e);
    }

    public void createSplash(int x, int y) {
        Splash e = new Splash(this, x, y);
        items.add(e);
    }

    public void createRubble(int x, int y) {
        Rubble r = new Rubble(this, x, y);
        items.add(r);
        map[y][x] = r;
    }

    public void gameOver() {
        canUndo = false;
        gameOver = true;
        busy++;
    }

    public void backUpAll() {
        backUp.clear();

        for (int i = 0; i < items.size(); i++) {
            AbstractSprite item = (AbstractSprite) items.get(i);

            if (item.getClass().equals(BlackPirate.class)) {
                BlackPirate b = new BlackPirate((BlackPirate) item);
                backUp.add(b);
            } else if (item.getClass().equals(RedPirate.class)) {
                RedPirate r = new RedPirate((RedPirate) item);
                backUp.add(r);
            } else if (item.getClass().equals(BluePirate.class)) {
                BluePirate b = new BluePirate((BluePirate) item);
                backUp.add(b);
            } else if (item.getClass().equals(GhostShip.class)) {
                GhostShip g = new GhostShip((GhostShip) item);
                backUp.add(g);
            } else if (item.getClass().equals(GoodShip.class)) {
                GoodShip g = new GoodShip((GoodShip) item);
                backUp.add(g);
            } else {
                backUp.add(item);
            }
        }
        canUndo = true;
    }

    public void setFromBackUp() {
        // Stream s = new MemoryStream(Encoding.ASCII.GetBytes(_backUp));
        // XmlSerializer xs = new XmlSerializer(typeof(List<MyUserControl>));

        // Items = (List<MyUserControl>)xs.Deserialize(s);
        if (!canUndo)
            return;

        // Items.Clear();

        // int i = 0;
        // while (i<Items.Count)
        // {
        // MyUserControl m = Items[i];
        // if (m.IsShip())
        // {
        // Items.RemoveAt(i);
        // Map[m.Y][m.X] = null;
        // }
        // else
        // i++;
        // }
        for (int i = 0; i < items.size(); i++) {
            AbstractSprite item = (AbstractSprite) items.get(i);
            map[item.Y][item.X] = null;
        }
        items.clear();

        for (int i = 0; i < backUp.size(); i++) {

            AbstractSprite control = (AbstractSprite) backUp.get(i);
            items.add(control);
            map[control.Y][control.X] = control;
            if (control.getClass().equals(GoodShip.class)) {
                mainShip = (GoodShip) control;
            }
        }

        // foreach (Ship ship in _backUp)
        // {
        // Items.Add(ship);
        // Map[ship.Y][ship.X] = ship;
        // if (ship.GetType().Equals(typeof(GoodShip)))
        // {
        // MainShip = (GoodShip)ship;
        // }
        // }
        canUndo = false;
    }

    @Override
    public boolean update() {
        int i = 0;
        for (AbstractLayer layer : layers) {
            layer.update();
        }
        while (i < this.items.size()) {
            if (this.items.get(i).update())
                i++;
        }
        return true;
    }

}
